/* -------------------------------------------------------------------------
 *  This file is part of the Cantian project.
 * Copyright (c) 2024 Huawei Technologies Co.,Ltd.
 *
 * Cantian is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *          http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 *
 * ctsql_table_func.h
 *
 *
 * IDENTIFICATION
 * src/ctsql/node/ctsql_table_func.h
 *
 * -------------------------------------------------------------------------
 */
#ifndef __SQL_TABLE_FUNC_H__
#define __SQL_TABLE_FUNC_H__

#include "ctsql_stmt.h"
#include "ctsql_context.h"
#include "ctsql_verifier.h"
#include "pl_debugger.h"
#include "pl_dbg_tab_func.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef status_t (*exec_table_func_t)(sql_stmt_t *stmt, table_func_t *func, knl_cursor_t *cursor);
typedef status_t (*fetch_table_func_t)(sql_stmt_t *stmt, table_func_t *func, knl_cursor_t *cursor);
typedef status_t (*verify_table_func_t)(sql_verifier_t *verf, sql_table_t *table);
typedef status_t (*set_parms_table_func_t)(sql_stmt_t *stmt, void *handle, sql_table_t *tab);
typedef status_t (*reset_parms_table_func_t)(sql_stmt_t *stmt, void *handle, void *session, sql_table_t *tab);

#define GET_TAB_ROWS_PARAMS_COUNT 6

// the method of getting rows
typedef enum en_table_func_method {
    TFM_MEMORY = 0,    // rs are generated by function
    TFM_TABLE_RS = 1,  // rs are from table/view
    TFM_TABLE_ROW = 2, // rows are from table/view
} table_func_method_t;

typedef tf_scan_flag_t (*get_tfm_scan_flag)(table_func_t *func);

typedef struct st_table_func_desc {
    text_t user;
    text_t package;
    text_t name;
    uint32 column_count;
    knl_column_t *columns;
    exec_table_func_t exec;
    fetch_table_func_t fetch;
    verify_table_func_t verify;
    set_parms_table_func_t pre_set_parms;
    reset_parms_table_func_t reset_parms;
    get_tfm_scan_flag get_scan_flag;

    void *hash_next;
    table_func_method_t method;
} table_func_desc_t;

typedef enum en_page_corrupt_type {
    PC_DATABASE = 0,
    PC_TABLESPACE,
    PC_DATAFILE,
    PC_PAGE,
} page_corrupt_type_t;

typedef struct st_pc_buf_head {
    page_corrupt_type_t pc_type;
    uint32 space_id;
    uint32 file_id;
    uint32 page_id;
} pc_buf_head_t;

#define IS_DYNAMIC_TBL_FUNC(fun_desc) ((fun_desc)->columns == NULL)

#define ARRAY_IN(arr) __array_in_##arr
#define ARRAY_IN_DEF(arr) uint32 __array_in_##arr = (sizeof(arr) / sizeof((arr)[0]));
#define ARRAY_IN_DECLARE(arr) extern uint32 __array_in_##arr;

extern knl_column_t g_analyze_table_columns[];
ARRAY_IN_DECLARE(g_analyze_table_columns)
extern knl_column_t g_breakpoint_info_columns[];
ARRAY_IN_DECLARE(g_breakpoint_info_columns)
extern knl_column_t g_proc_decode_columns[];
ARRAY_IN_DECLARE(g_proc_decode_columns)
extern knl_column_t g_proc_callstack_columns[];
ARRAY_IN_DECLARE(g_proc_callstack_columns)
extern knl_column_t g_table_paralel_columns[];
ARRAY_IN_DECLARE(g_table_paralel_columns)
extern knl_column_t g_insert_dist_ddl_columns[];
ARRAY_IN_DECLARE(g_insert_dist_ddl_columns)
extern knl_column_t g_show_values_columns[];
ARRAY_IN_DECLARE(g_show_values_columns)
extern knl_column_t g_proc_line_columns[];
ARRAY_IN_DECLARE(g_proc_line_columns)
extern knl_column_t g_control_info_columns[];
ARRAY_IN_DECLARE(g_control_info_columns)
extern knl_column_t g_dba_free_space_columns[];
ARRAY_IN_DECLARE(g_dba_free_space_columns)


#define PROC_LINE_VALUE_SIZE sizeof(dba_proc_line_record_t)
#define PROC_SOURCE_HEAD_RESERVED_LEN 158 // create or replace procedure(function/trigger) <object_name>
#define PROC_SOURCE_HEAD_OFFSET PROC_LINE_VALUE_SIZE
#define PROC_SOURCE_OFFSET (PROC_SOURCE_HEAD_OFFSET + PROC_SOURCE_HEAD_RESERVED_LEN)

status_t sql_fetch_table_func(sql_stmt_t *stmt, table_func_t *func, knl_cursor_t *cursor, bool32 *eof);
status_t sql_exec_table_func(sql_stmt_t *stmt, table_func_t *func, knl_cursor_t *cursor);
status_t sql_describe_table_func(sql_verifier_t *verf, sql_table_t *table, uint32 tbl_id);

status_t table_func_verify(sql_verifier_t *verf, table_func_t *tab_func, uint16 min_args, uint16 max_args);
status_t table_cast_fetch_core(sql_stmt_t *stmt, table_func_t *func, knl_cursor_t *cursor, row_assist_t *row_ass);
status_t sql_exec_tablefunc_arg(sql_stmt_t *stmt, expr_tree_t *expr, variant_t *value, ct_type_t type,
    bool32 check_null);
status_t get_page_corruption_scan_type(text_t *type, page_corrupt_type_t *pc_type);
bool32 pc_verify_parameter_combination(page_corrupt_type_t type, expr_tree_t *arg2, expr_tree_t *arg3);
bool32 pc_verify_value_vaild(knl_session_t *session, knl_cursor_t *cur, page_corrupt_type_t pc_type,
    variant_t *common_id, uint32 *space_id);
void pc_init_cursor_pagebuf(knl_cursor_t *cur, page_corrupt_type_t pc_type, uint32 space_id);
status_t dba_page_corruption_scan(knl_session_t *session, knl_cursor_t *cursor);
void pc_update_db_position(knl_session_t *session, knl_cursor_t *cur);
void pc_update_spc_position(knl_session_t *session, uint32 space_id, knl_cursor_t *cur);
void pc_update_df_position(knl_session_t *session, uint32 file_id, knl_cursor_t *cursor);
status_t dba_file_corruption_scan(knl_session_t *session, knl_cursor_t *cursor);

status_t pending_trans_session_args(sql_stmt_t *stmt, table_func_t *func, variant_t *fmt_id, variant_t *global_tran_id,
    variant_t *branch_id);
status_t pending_trans_session_put(session_t *session, knl_cursor_t *cursor, variant_t *global_tran_id,
    variant_t *branch_id);
status_t read_lob_value(sql_stmt_t *stmt, variant_t *val, text_t *ddl_info);
status_t dba_verify_index_by_name(knl_session_t *session, knl_cursor_t *cursor, knl_dictionary_t *dc,
    text_t *index_name, bool8 *is_corrupt);
status_t dba_verify_table(knl_session_t *session, knl_cursor_t *cursor, knl_dictionary_t *dc, bool8 *is_corrupt);


#define FUNC_TABLE_COST 512

#ifdef __cplusplus
}
#endif

#endif
